using System;
using System.Collections.Generic;
using System.Text;
using AntEater.ComponentModel.BuildElements;
using System.ComponentModel;

namespace AntEater.ComponentModel
{
    /// <summary>
    /// Provides an enumaration of the different message types.
    /// </summary>
    public enum MessageType
    {
        /// <summary>
        /// An information message.
        /// </summary>
        Info = 0,

        /// <summary>
        /// A warning message.
        /// </summary>
        Warning = 1,

        /// <summary>
        /// An error message.
        /// </summary>
        Error = 2
    }

    /// <summary>
    /// Provides an enumaration of the different message categories.
    /// </summary>
    public enum MessageCategory
    {
        /// <summary>
        /// A miscellaneous message.
        /// </summary>
        Miscellaneous = 0,

        /// <summary>
        /// A transformation message.
        /// </summary>
        Transformation = 1,

        /// <summary>
        /// A validation message.
        /// </summary>
        Validation = 2
    }

    /// <summary>
    /// Represents a message.
    /// </summary>
    [Serializable]
    public class Message : INotifyPropertyChanged
    {

        /// <summary>
        /// Occurs when the instance or some of his child objects has changed.
        /// </summary>
        public event EventHandler<EventArgs> Changed;

        /// <summary>
        /// Occurs when a property of the instance has changed
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Initializes a new instance of the <see cref="T:Message"/> class.
        /// </summary>
        /// <param name="text">The text.</param>
        public Message(string text)
            : this(text, MessageType.Info, MessageCategory.Miscellaneous, null) {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="T:Message"/> class.
        /// </summary>
        /// <param name="text">The text.</param>
        /// <param name="type">The type.</param>
        public Message(string text, MessageType type)
            : this(text, type, MessageCategory.Miscellaneous, null) {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="T:Message"/> class.
        /// </summary>
        /// <param name="text">The text.</param>
        /// <param name="category">The category.</param>
        public Message(string text, MessageCategory category)
            : this(text, MessageType.Info, category, null) {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="T:Message"/> class.
        /// </summary>
        /// <param name="text">The text.</param>
        /// <param name="type">The type.</param>
        /// <param name="category">The category.</param>
        public Message(string text, MessageType type, MessageCategory category)
            : this(text, type, category, null) {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="T:Message"/> class.
        /// </summary>
        /// <param name="text">The text.</param>
        /// <param name="type">The type.</param>
        /// <param name="category">The category.</param>
        /// <param name="buildElement">The build element.</param>
        public Message(string text, MessageType type, MessageCategory category, IBuildElement buildElement) {
            this._text = text;
            this._type = type;
            this._category = category;
            this._buildElement = buildElement;
        }

        private IBuildElement _buildElement;

        /// <summary>
        /// Gets or sets the build element.
        /// </summary>
        /// <value>The build element.</value>
        public IBuildElement BuildElement {
            get { return _buildElement; }
        }

        private string _text;

        /// <summary>
        /// Gets or sets the message.
        /// </summary>
        /// <value>The message.</value>
        public string Text {
            get { return _text; }
        }

        private MessageType _type;

        /// <summary>
        /// Gets or sets the type.
        /// </summary>
        /// <value>The type.</value>
        public MessageType Type {
            get { return _type; }
        }

        private MessageCategory _category;

        /// <summary>
        /// Gets or sets the category.
        /// </summary>
        /// <value>The category.</value>
        public MessageCategory Category {
            get { return _category; }
        }

        /// <summary>
        /// Called when [changed].
        /// </summary>
        protected void OnChanged() {
            if (this.Changed != null) {
                this.Changed(this, new EventArgs());
            }
        }

        /// <summary>
        /// Called when [property changed].
        /// </summary>
        /// <param name="propertyName">Name of the property.</param>
        protected void OnPropertyChanged(string propertyName) {
            if (this.PropertyChanged != null) {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }

            this.OnChanged();
        }

        /// <summary>
        /// Returns a <see cref="T:System.String"></see> that represents the current <see cref="T:System.Object"></see>.
        /// </summary>
        /// <returns>
        /// A <see cref="T:System.String"></see> that represents the current <see cref="T:System.Object"></see>.
        /// </returns>
        public override string ToString() {

            string result = string.Empty;
            result += _category.ToString();
            if (!string.IsNullOrEmpty(_text)) {
                result += _text;
            }
            if (string.IsNullOrEmpty(result)) {
                result = base.ToString();
            }

            return result;
        }
    }
}
